<?php
class PkController extends Controller
{

	public function actionIndex(){
		$pictures = $this->_getGroupedData();
        $picIds = array();
        foreach ($pictures as $key => $group) {
            $ids = array();
            foreach ($group as $pic) {
                $ids[] = $pic['id'];
            }
            $picIds[] = $ids;
        }
        $this->checkStart($picIds);
        $user = $_SESSION['user'];
        if($user){
            $user['game_count'] +=1;
            $modUser = new User();
            $_SESSION['user'] = $user;
            $modUser->save($user);
        }


		$arrTplData['pictures'] = $pictures;
		$arrTplData['jsonPictures'] = json_encode($pictures);
		$this->renderFile("pk/index.tpl", $arrTplData);
	}

    private function checkStart($pids){
        $user = $_SESSION['user'];
        if($user){
            $checkData = array(
                'uid' => $user['id'],
                'round' => 1,
                'pids' => $pids,
            );
            $hour = 3600;
            $key = 'game_'.$user['id'];
            Yii::app()->cache->set($key, $checkData, $hour);
        }
    }

    private function checkRound($p1, $p2){
        $user = $_SESSION['user'];
        if($user){
            $key = 'game_'.$user['id'];
            $checkData = Yii::app()->cache->get($key);
            if($checkData){
                $pids = $checkData['pids'];
                $round = $checkData['round'];
                
                $group = $pids[$round];
                if(in_array($p1['id'], $group)
                    && in_array($p2['id'], $group)){
                    //正确, 更新局数
                    $hour = 3600;
                    Yii::app()->cache->set($key, $checkData, $hour);
                    return true;
                } else {
                    //伪造player数据
                    return false;
                }
            } else {
                //超时或伪造user数据
                return false;
            }
        }
    }

    private function checkEnd(){
        $user = $_SESSION['user'];
        if($user){
            $key = 'game_'.$user['id'];
            Yii::app()->cache->delete($key);
        }
    }

    private function nextCheckRound(){
        $user = $_SESSION['user'];
        if($user){
            $key = 'game_'.$user['id'];
            $checkData = Yii::app()->cache->get($key);
            $checkData['round'] ++;
            $hour = 3600;
            Yii::app()->cache->set($key, $checkData, $hour);
        }
    }

    private function getCurrentRound(){
        $user = $_SESSION['user'];
        if($user){
            $key = 'game_'.$user['id'];
            $data = Yii::app()->cache->get($key);
            return $data['round'];
        }
        return 0;
    }

    private function markPrizeToChoose($prizes){
        $user = $_SESSION['user'];
        //安全隐患, 伪造奖
        $key = 'prize_'.$user['id'];
        $hour = 3600;
        Yii::app()->cache->set($key,$prizes, $hour);
    }

    private function getPrizeToChoose(){
        $user = $_SESSION['user'];
        if($user){
            $key = 'prize_'.$user['id'];
            return Yii::app()->cache->get($key);
        }
        return ;
    }

    private function markPrizeChoosen($prize){
        $user = $_SESSION['user'];
        $key = 'prize_'.$user['id'];
        Yii::app()->cache->delete($key);
        //TODO 持久化
    }
    



    //按score逆序
    private function _cmpScore($a, $b){
        return ($a['score'] < $b['score']) ? 1 : -1;
    }

    //返回分组数据(组数, 每组人数, 难度系数(大于1有效) )
	private function _getGroupedData($groupCount=40, $groupMembers=2, $hard=2.2){
    	$modPicture = new Picture();
    	$arrParams = array();
    	$arrParams['fields'] = 'id,pic_show_url,source,add_time';
    	$arrParams['where'] = 'rate_count <> 0';
        /** 
        //FIXME XXX remove this after test.
        //'add_time >= '. TimeUtil::yesterday() .' AND add_time < '. TimeUtil::today();
        */
        $modPicture->setParams($arrParams);
    	$arrPictureList = $modPicture->getList();
    	//shuffle($arrPictureList);
        //$subList = $groupCount == -1 ? 
        //    $arrPictureList : array_slice($arrPictureList, 0, $groupCount * $groupMembers);
        
        //1. 通过难度系数取出多余的待筛选数据viewport.
        $viewport = $hard > 1 ? intval($groupCount * $hard) : $groupCount;
        $viewport = ($viewport * $groupMembers) >= count($arrPictureList) ? count($arrPictureList)/$groupMembers : $viewport;


        $arrViewportKeys = array_rand($arrPictureList, $viewport * $groupMembers);
        $arrViewport = array();
        foreach ($arrViewportKeys as $idx) {
            $arrViewport[] = $arrPictureList[$idx];
        }
        //2. viewport排序后取出 $groupCount * $groupMembers 个子数组.
        usort($arrViewport, array('PkController', '_cmpScore'));
        $intSlice = rand(0, ($viewport - $groupCount) * $groupMembers );
        $subList = array_slice($arrViewport, $intSlice, $groupCount * $groupMembers);


        /*
        //取出随机的$groupCount的数组
        $subListKeys = array_rand($arrPictureList, $groupCount == -1 ? count($arrPictureList) : $groupCount);
        foreach ($subListKeys as $idx) {
            $subList[] = $arrPictureList[$idx];
        }
        //usort($subList, array('PkController', '_cmpScore'));
        */
        
        //3. 分组
        $groups = array_chunk($subList, $groupMembers);
        //4. 组间shuffle 避免高分一直在前
        shuffle($groups);
        //5. 组内shuffle
        foreach ($groups as $key => $value) {
            shuffle($value);
        }
        
    	return $groups; 
    }

	public function actionData(){
		echo json_encode($this->_getGroupedData());
		//return json_encode($this->_getData());
	}

	public function actionPk(){

        //TODO gamify. 扣鲜花, 取奖品
        $w = intval($_REQUEST['w']);
        $l = intval($_REQUEST['l']);
        //TODO 利用ip和token防作弊
        //将 id1_id2_ip 保存成一条记录,如果已存在,则不加分不减分.
        //token是 id1,id2,ip和timestamp共同运算的一个值,时间有效范围为前后半小时.
        //所有作弊策略不影响用户展示.作弊用户所见与正常用户没有区别,只是不计入分数.
        $ip = IpUtil::getRealIp();//$_SERVER['REMOTE_ADDR'];
        $token = $_REQUEST['token'];

        $modPicture = new Picture();
        $modPicture->setParams(array('id'=>$w));
        $a = $modPicture->getItem();
        $modPicture->setParams(array('id'=>$l));
        $b = $modPicture->getItem();

        //扣鲜花
        $this->updateUserFlowers();

        // 检验作弊
        $check = $this->checkRound($a, $b);
        if(! $check){
            //作弊
            return;
        }

        //该局结果
        $result = $a['score'] >= $b['score'] ? 1 : 0;

        if(! $result){ //失败
            //标识用户赢得局数
            $user = $_SESSION['user'];
            $user['win_round_count'] = $this->getCurrentRound() -1;
            $modUser = new User();
            $_SESSION['user'] = $user;
            $modUser->save($user);
            //结束state
            $this->checkEnd();
            echo(json_encode(array('win'=>0)));
            //TODO game记录, user total_round win_round 更新
        } else { // 成功
            $prizes = PrizeService::getPrizesByRound($this->getCurrentRound());
            $this->markPrizeToChoose($prizes);
            //state 局数+1
            $this->nextCheckRound();
            $json_data = array(
                'win' => $result,
                'prize' => $prizes,
            );
            echo(json_encode($json_data));
        }

        $this->updateScore($a, $b);
        //echo("Before:<br>w.score:".$a['score'].'<br>');
        //echo("l.score:".$b['score'].'<br>');
        
	}

    //领取礼品
    public function actionPrizeChoosen(){
        $prizeId = intval(Yii::app()->request->getParam('prizeId', 0));
        $user = $_SESSION['user'];
        if($user){
            $uid = $user['id'];
            $prizes = $this->getPrizeToChoose();
            if(! $prizes){ //奖品逾期未领或伪造奖品数据
                return ;
            }
            $pids = array();
            foreach ($prizes as $prize) {
                $pids[] = $prize['id'];
            }
            if(!in_array($prizeId, $pids)){ //伪造奖品数据
                return;
            }
            $modPrize = new Prize();
            $modPrize->setParams(array('id'=>$prizeId));
            $thePrize = $modPrize->getItem();
            if(!$thePrize['id']){ //伪造奖品数据
                return;
            }
            $cashed = 0;
            if($thePrize['must_cash_now']){
                $cashed = 1;
                $user['flowers'] += $thePrize['flowers'];
            }

            $user['win_game_count'] += 1;
            $user['win_round_count'] += $this->getCurrentRound() -1;

            $modUser = new User();
            $_SESSION['user'] = $user;
            $modUser->save($user);

            //清除游戏状态标识
            $this->checkEnd();

            $modUserPrize = new UserPrize();
            $userPrize = array(
                'uid' => $uid,
                'prize_id' => $prizeId,
                'is_cashed' => $cashed,
                'time' => TimeUtil::now(),
            );
            $modUserPrize->save($userPrize);
            echo(json_encode(array('success'=>1)));
        }
        
    }

    private function updateScore($a, $b){
        //facemash 核心算法开始
        $c = (doubleval($a["score"])-doubleval($b["score"]))/400;
        
        $e = pow(10,$c);
        $ea = 1/(1+$e);
        $eb = 1/(1+1/$e);
        $r = 32*$ea;
        
        $a["score"] = doubleval($a["score"]) + $r;
        $b["score"] = doubleval($b["score"]) - $r;
        //facemash 核心算法结束
        $a['win'] = $a['win'] + 1;
        $b['lose'] = $b['lose'] + 1;
        
        $modPicture = new Picture();
        $modPicture->save($a);
        $modPicture->save($b);   
    }

    //扣鲜花
    public function updateUserFlowers(){
        $user = $_SESSION['user'];
        $roundCost = Yii::app()->params['game']['roundCost'];

        if($user['flowers'] < $roundCost){
            if(Yii::app()->request->isAjaxRequest){
                echo '{"error":"NoMoney"}';
                exit();
            } else {
                Yii::app()->request->redirect('/user/charge');
            }
        }
        $user['flowers'] = $user['flowers'] - $roundCost;

        $_SESSION['user'] = $user;
        $modelUser = new User();
        $modelUser->save($user);
    }

	public function actionRank(){
        $modPicture = new Picture();
        $arrParams = array();
        $arrParams['fields'] = 'id,pic_show_url,source,add_time';
        $arrParams['orderby'] = array('score'=>'desc');
        $arrParams['offset'] = 0;
        $arrParams['limit'] = 10;
        $arrParams['where'] = 'add_time >= '. TimeUtil::yesterday() .' AND add_time < '. TimeUtil::today();
        /** 
        //$arrParams['where'] = 'rate_count <> 0';
        //FIXME XXX remove this after test.
        //'add_time >= '. TimeUtil::yesterday() .' AND add_time < '. TimeUtil::today();
        */
        $modPicture->setParams($arrParams);
        $arrPictureList = $modPicture->getList();

        $arrTplData = array(
            'arrPictureList' => $arrPictureList
        );
		$this->renderFile("pk/rank.tpl", $arrTplData);
	}

    public function actionTemp(){
        $modPicture = new Picture();
        //$modPicture->setParams(array('condition'=>array('is_del'=>1)));
        $picList = $modPicture->getList();
        $i = 0;
        foreach ($picList as $key => $item) {
            if(strlen($item['uniq_sign'])<2 ){
                $item['uniq_sign'] = 'rand_'.round(rand()*100);
                $modPicture->save($item);
                $i ++;
            }
        }
        echo('ok'.$i);
    }

}